<?php

/*
Plugin Name: My Feed Stats
Plugin URI: http://tech.idv2.com/2007/11/12/my-feed-stats/
Description: feed订阅者统计插件，提供类似于FeedBurner的条形统计图。
Version: 1.0.1
Author: charlee
Author URI: http://tech.idv2.com/
*/


/*
Copyright 2006-2007 idv2.com (email : oda.charlee@gmail.com)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/


define(WP_MFS_ABSPATH, ABSPATH . "wp-content/plugins/my-feed-stats/");

MY_FEED_STATS::check_for_install();
/**
 * 定义类，避免命名冲突
 */
class MY_FEED_STATS {

	static $readers = null;

	/**
	 * 检查是否安装并建立需要的表
	 */
	function check_for_install() {

		global $wpdb, $table_prefix;

		$installed_version = get_option('wp_mfs_version');
		list($major, $minor, $patch) = explode('.', $installed_version);

		if ($major < 1) {
			$readers = $table_prefix."mfs_readers";
			$user_agent = $table_prefix."mfs_user_agent";
			$subscribers = $table_prefix."mfs_subscribers";

			$sql = <<<SQL
CREATE TABLE IF NOT EXISTS $readers (
  ID int(11) NOT NULL auto_increment,
  identifier varchar(64) NOT NULL default '',
  name varchar(255) NOT NULL default '',
  type varchar(16) NOT NULL default '',
  description text NOT NULL,
  PRIMARY KEY  (ID)
) ENGINE=MyISAM;
SQL;

			$wpdb->query($sql);

			$sql = <<<SQL
CREATE TABLE IF NOT EXISTS $subscribers (
  ID int(11) NOT NULL auto_increment,
  reader_id int(11) NOT NULL default '0',
  count int(11) NOT NULL default '0',
  stat_date date NOT NULL default '0000-00-00',
  PRIMARY KEY  (ID)
) ENGINE=MyISAM;
SQL;

			$wpdb->query($sql);

			$sql = <<<SQL
CREATE TABLE $user_agent (
  ID int(11) NOT NULL auto_increment,
  ip varchar(16) NOT NULL default '',
  user_agent varchar(255) NOT NULL default '',
  access_time datetime NOT NULL default '0000-00-00 00:00:00',
  is_fresh enum('Y','N') NOT NULL default 'Y',
  PRIMARY KEY  (ID)
) ENGINE=MyISAM;
SQL;

			$wpdb->query($sql);

			add_option('wp_mfs_version', '1.0.0', 'version');
			add_option('wp_mfs_imgpath', 'feeds.png', 'image path for generated subscriber picture');
			add_option('wp_mfs_imgcolor', '#FF0000', 'color of subscriber picture');
			add_option('wp_mfs_sitename', 'tech.idv2.com');
		}
	}

	/**
	 * 每次请求feed时调用此函数
	 */
	function feed_request() {
		global $wpdb, $table_prefix;

		if (MY_FEED_STATS::is_feed_url()) {
			MY_FEED_STATS::save_request();
			MY_FEED_STATS::check_stats();
		}
	}


	/**
	 * 保存访问记录
	 */
	function save_request() {
		global $wpdb, $table_prefix;

		$remote_addr = $_SERVER['REMOTE_ADDR'];
		$user_agent = $_SERVER['HTTP_USER_AGENT'];

		$user_agent = trim($user_agent);
		// 如果$user_agent为空则直接忽略。否则会导致灾难性错误 :-(
		if (!$user_agent) return;

		if (!preg_match("/(subscriber|user|readers)/i", $user_agent)) {
			// 首先过滤掉各种浏览器
			// 这一步有可能连Firefox Live Bookmark一起过滤掉，暂时先不考虑它了
			if (preg_match("/(Firefox|Opera|MSIE|Safari|Webryreader)/i", $user_agent)) {
				return;
			}

			// 过滤掉各种bot
			if (preg_match("/(slurp|bot|spider)/i", $user_agent)) {
				return;
			}
		}

		// 然后做数据收集
		$sql = "INSERT INTO ".$table_prefix."mfs_user_agent
			(ip, user_agent, access_time, is_fresh)
			VALUES ('$remote_addr', '$user_agent', NOW(), 'Y')";
		$wpdb->query($sql);
	}

	/**
	 * 检查是否应当进行统计
	 */
	function check_stats() {
		global $wpdb, $table_prefix;

		$yesterday = date('Y-m-d', time()-86400);

		// 统计昨天的未统计数据数目
		$sql = "SELECT COUNT(access_time) AS count FROM ".$table_prefix."mfs_user_agent 
			WHERE is_fresh='Y' AND access_time>='$yesterday 00:00:00'
			AND access_time<='$yesterday 23:59:59'";
		$r = $wpdb->query($sql);
		if ($r > 0) {
			$row = $wpdb->last_result;
			$yesterday_count = $row[0]->count;

			// 如果昨天有未统计的结果，则统计之
			if ($yesterday_count > 0) {
				MY_FEED_STATS::make_stats();
			}
		}

	}


	/**
	 * 判断请求是否是feed请求
	 * @private
	 */
	function is_feed_url() {
		$req_uri = $_SERVER['REQUEST_URI'];
		$self = $_SERVER['PHP_SELF'];
		$pathinfo = $_SERVER['PATH_INFO'];

		// 如果URI中包含了 /feed 则认为是feed请求
		if (preg_match("!/feed!", $req_uri)) {
			return true;
		}

		// 如果脚本名称是feed脚本则认为是feed请求
		switch (basename($self)) {
		case 'wp-rdf.php':
		case 'wp-rss.php':
		case 'wp-rss2.php':
		case 'wp-atom.php':
			return true;
			break;
		}

		// 如果查询参数包括了feed变量则认为是feed请求
		if (isset($_GET["feed"])) {
			return true;
		}

		return false;
	}


	/**
	 * 统计前一天的定阅量
	 */
	function make_stats() {
		global $wpdb, $table_prefix;

		// 获取所有的阅读器标识
		MY_FEED_STATS::get_reader_identifier();

		// 取出所有尚未统计的访问
		$sql = "SELECT * FROM ".$table_prefix."mfs_user_agent WHERE is_fresh='Y' ORDER BY ID";
		$r = $wpdb->query($sql);

		if ($r > 0) {
			// 阅读器订阅者计数器
			$reader_count = array();
			$ip_hash = array();

			// 依次取得每一条访问记录并进行统计
			$row = $wpdb->last_result;
			
			// 记录下id的范围以便删除记录
			$id_min = $row[0]->ID;
			$id_max = $row[$r-1]->ID;

			for ($i = 0; $i < $r; $i++) {

				$user_agent = $row[$i]->user_agent;
				$ip = $row[$i]->ip;

				// 如果user_agent为空则直接进行下一条
				if (!$user_agent) continue;

				// 获取该阅读器的id
				$reader_id = MY_FEED_STATS::get_reader_id($user_agent);
				$reader_type = MY_FEED_STATS::$readers[$reader_id]["type"];

				// 根据阅读器的类别分别进行统计
				switch ($reader_type) {
					case 'online':
						// 在线阅读器仅关心它声明的subscribers数目
						// 获取subscribers数目
						if (preg_match("/(\d+)\s+subscribers/i", $user_agent, $matches)) {
							$subscribers = $matches[1];
						} else {
							$subscribers = 1;			// 如果阅读器没给出订阅者数则算1
						}

						if (!isset($reader_count[$reader_id]) || $reader_count[$reader_id] < $subscribers) { 
							$reader_count[$reader_id] = $subscribers;
						}
						break;

					case 'offline':
						// 离线阅读器对每一次访问进行计数，但同一个IP地址不会被记录多次
						if (!isset($ip_hash[$ip])) {
							$ip_hash[$ip] = 1;
							if (!isset($reader_count[$reader_id])) {
								$reader_count[$reader_id] = 0;
							}
							$reader_count[$reader_id]++;
						}
						break;
					case 'bot':
					case 'browser':
						// bot或者浏览器则直接略掉
						break;
					default:
						break;
				}
			}

			// 将统计结果保存到数据库中
			$total_subscribers = 0;
			foreach ($reader_count as $reader_id => $subscribers) {
				$sql = "INSERT INTO ".$table_prefix."mfs_subscribers (reader_id,count,stat_date) VALUES
					($reader_id,$subscribers,NOW())";
				$wpdb->query($sql);
				$total_subscribers += $subscribers;
			}

			// 生成订阅者数图片
			MY_FEED_STATS::generate_image($total_subscribers);

			// 删除本次处理过的记录
			$sql = "UPDATE ".$table_prefix."mfs_user_agent SET is_fresh='N' WHERE ID>=$id_min AND ID<=$id_max";
			$wpdb->query($sql);
		}
	}

	/**
	 * 获取所有的阅读器标识
	 */
	function get_reader_identifier() {
		global $wpdb, $table_prefix;

		$sql = "SELECT ID,identifier,type FROM ".$table_prefix."mfs_readers";
		
		if ($wpdb->query($sql) > 0) {
			$row = $wpdb->last_result;
			foreach ($row as $r) {
				MY_FEED_STATS::$readers[$r->ID] = array("identifier" => $r->identifier, "type" => $r->type);
			}
		}
	}


	/**
	 * 获取阅读器id
	 */
	function get_reader_id($user_agent) {
		global $wpdb, $table_prefix;

		if (MY_FEED_STATS::$readers) {
			foreach (MY_FEED_STATS::$readers as $id => $reader) {
				if (strpos($user_agent, $reader["identifier"]) !== FALSE) {
					return $id;
				}
			}
		}

		// 如果没有找到匹配的阅读器，则猜测该阅读器的情况
		$type = "offline";
		if (preg_match("/(subscriber|user|readers)/i", $user_agent)) {
			$type = "online";
		}

		$name = explode(" ", $user_agent);
		$name = $identifier = $name[0];

		// 将猜测结果保存到数据库中
		$sql = "INSERT INTO ".$table_prefix."mfs_readers (name,identifier,type) VALUES
			('$user_agent','$identifier','$type')";
		$wpdb->query($sql);


		// 再次尝试获取阅读器id
		MY_FEED_STATS::get_reader_identifier();
		return MY_FEED_STATS::get_reader_id($user_agent);
	}


	/**
	 * 生成订阅者数图片
	 */
	function generate_image($num) {

		$img_color = get_option('wp_mfs_imgcolor');
		$img_path = get_option('wp_mfs_imgpath');
		$sitename = get_option('wp_mfs_sitename');

		if (!preg_match('/^\#[0-9A-Fa-f]{6}$/', $img_color)) {
			$img_color = "#FF0000";
		}

		MY_FEED_IMAGE::generate_image($num, $img_color, $sitename, ABSPATH . $img_path);
	}


	/**
	 * 添加管理界面
	 */
	function add_admin_menu() {
		add_submenu_page('edit.php', 'Feed统计', 'Feed统计', 8, 'mfs_statistics', 'wp_mfs_statistics');
	}

}


class MY_FEED_IMAGE {

	/**
	 * 生成订阅数目的图片
	 * @param int $num 图片上显示的订阅数
	 * @param string $color #rrggbb或者#rgb格式的颜色值
	 * @param string $file 生成的图片的文件名
	 */
	function generate_image($num, $color, $sitename, $file) {

		// 生成图片时的一些配置信息
		$icon_width = 88;
		$icon_height = 26;
		$rect_width = $icon_width;
		$rect_height = 17;
		$window_width = 38;
		$window_height = 14;
		$Y_diff = 40;			// 深色和浅色的辉度差
		$Cb_diff = -20;			// 饱和度的差别

		$im = imagecreatetruecolor($icon_width, $icon_height);

		// 正常背景色的颜色
		list($r, $g, $b) = MY_FEED_IMAGE::transform_color($color);

		// 稍稍浅一些的背景色
		list($Y, $Cr, $Cb) = MY_FEED_IMAGE::RGB2YCbCr($r, $g, $b);
		list($r1, $g1, $b1) = MY_FEED_IMAGE::YCbCr2RGB(MY_FEED_IMAGE::check_range($Y+$Y_diff), $Cr, MY_FEED_IMAGE::check_range($Cb+$Cb_diff));
		list($r2, $g2, $b2) = MY_FEED_IMAGE::YCbCr2RGB(MY_FEED_IMAGE::check_range($Y-$Y_diff), $Cr, $Cb);

		// 分配颜色
		$bg = imagecolorallocate($im, 0xFF, 0xFF, 0xFF);	// 全体背景色
		$bg1 = imagecolorallocate($im, $r, $g, $b);			// 原色
		$bg2 = imagecolorallocate($im, $r1, $g1, $b1);		// 浅色
		$bd1 = imagecolorallocate($im, 0xDD, 0xDD, 0xDD);	// 高光
		$bd2 = imagecolorallocate($im, $r2, $g2, $b2);	// 阴影
		if ($Y >= 128) {
			$tc1 = imagecolorallocate($im, 0, 0, 0);
		} else {
			$tc1 = imagecolorallocate($im, 0xFF, 0xFF, 0xFF);
		}
		$tc2 = imagecolorallocate($im, 0, 0, 0);

		// 绘制底色的矩形
		imagefilledrectangle($im, 0, 0, $icon_width-1, $icon_height-1, $bg);
		imagefilledrectangle($im, 0, 0, $rect_width-1, $rect_height-1, $bg1);
		imagefilledrectangle($im, 3, 3, $window_width-1, $window_height-1, $bg2);

		// 绘制高光和阴影
		imageline($im, 0, 0, $rect_width-1, 0, $bd1);
		imageline($im, 0, 0, 0, $rect_height-1, $bd1);
		imageline($im, $rect_width-1, 0, $rect_width-1, $rect_height-1, $bd2);
		imageline($im, 0, $rect_height-1, $icon_width-1, $rect_height-1, $bd2);
		imageline($im, 2, 2, $window_width-1, 2, $bd2);
		imageline($im, 2, 2, 2, $window_height-1, $bd2);
		imageline($im, $window_width-1, 2, $window_width-1, $window_height-1, $bd1);
		imageline($im, 2, $window_height-1, $window_width-1, $window_height-1, $bd1);

		// 写数字和文字
		$font = imageloadfont(WP_MFS_ABSPATH . "terminal6-modified.gdf");
		imagestring($im, $font, 5, 5, str_pad($num, 5, ' ', STR_PAD_LEFT), $tc1);
		imagestring($im, $font, $window_width+3, 5, "readers", $tc1);
		imagestring($im, $font, 5, $rect_height+1, $sitename, $tc2);

		imagepng($im, $file);

		imagedestroy($im);
	}

	/**
	 * 将#RRGGBB格式的颜色数据转化成整数
	 * @param string $color 表示颜色的字符串，$RRGGBB或者#RGB的格式
	 * @type Array
	 * @return 包含红绿蓝三色的数组(r, g, b)
	 */
	function transform_color($color) {

		$r = $g = $b = 0;

		// 处理 #rgb 格式的颜色
		if (preg_match('/^#?([A-Fa-f0-9]{3})$/', $color, $match)) {
			$color = $match[1];
			$r = str_repeat(substr($color, 0, 1), 2);
			$g = str_repeat(substr($color, 1, 1), 2);
			$b = str_repeat(substr($color, 2, 1), 2);

		// 处理 #rrggbb 格式的颜色
		} else if (preg_match('/^#?([A-Fa-f0-9]{6})$/', $color, $match)) {
			$length = 6;
			$color = $match[1];
			$r = substr($color, 0, 2);
			$g = substr($color, 2, 2);
			$b = substr($color, 4, 2);
		}

		// 将颜色字符串转换成十进制数返回
		return array(hexdec($r), hexdec($g), hexdec($b));
	}	


	/**
	 * RGB模式颜色转换成YCbCr模式颜色
	 *
	 * 变换公式：
	 * Y  =  (0.2990 * R) + (0.5870 * G) + (0.1140 * B)
	 * Cb = -(0.1687 * R) - (0.3313 * G) + (0.5000 * B) + 128
	 * Cr =  (0.5000 * R) - (0.4187 * G) - (0.0813 * B) + 128
	 *
	 * @param int $r 红色分量
	 * @param int $g 绿色分量
	 * @param int $b 蓝色分量
	 * @type array
	 * @return 用YCbCr格式表示的颜色的数组
	 */
	function RGB2YCbCr($r, $g, $b) {

		$Y  =  (0.2990 * $r) + (0.5870 * $g) + (0.1140 * $b);
		$Cb = -(0.1687 * $r) - (0.3313 * $g) + (0.5000 * $b) + 128;
		$Cr =  (0.5000 * $r) - (0.4187 * $g) - (0.0813 * $b) + 128;

		return array($Y, $Cb, $Cr);
	}


	/**
	 * YCbCr模式颜色转换成RGB格式颜色
	 *
	 * 变换公式：
	 * R = Y + ((Cr-128) * 1.4020)
	 * G = Y - ((Cb-128) * 0.3441) - ((Cr-128) * 0.7139)
	 * B = Y + ((Cb-128) * 1.7718)
	 *
	 * @param int $Y 辉度分量
	 * @param int $Cb 色度分量
	 * @param int $Cr 饱和度分量
	 * @type array
	 * @reutrn 用RGB格式表示的颜色数组
	 */
	function YCbCr2RGB($Y, $Cb, $Cr) {

		$r = MY_FEED_IMAGE::check_range($Y + (($Cr-128) * 1.4020));
		$g = MY_FEED_IMAGE::check_range($Y - (($Cb-128) * 0.3441) - (($Cr-128) * 0.7139));
		$b = MY_FEED_IMAGE::check_range($Y + (($Cb-128) * 1.7718));

		return array($r, $g, $b);
	}

	/**
	 * 确保颜色值范围在0～255之间
	 * @param int $n 输入颜色值
	 * @type int
	 * @return 0～255之间的颜色值
	 */
	function check_range($n) {

		if ($n < 0) $n = 0;
		else if ($n > 255) $n = 255;

		return $n;
	}
}


/********************************************************************************/

/**
 * 以下是全局函数，用于管理界面
 */





/**
 * 管理界面
 */
function wp_mfs_statistics() {
	$func = $_GET['f'];

	if ($func == 'e') {
		// 编辑阅读器的定义
		wp_mfs_edit_readers_definition();
		return;

	} else if ($func == 'es') {
		// 保存编辑器定义
		wp_mfs_save_readers_definition();
	
	} else if ($func == 'uo') {
		// 保存选项
		wp_mfs_save_option();

	} else if ($func == 'du') {
		// 删除旧的UserAgent数据
		wp_mfs_delete_old_useragent();

	} else if ($func == 'rg') {
		// 强制重新生成订阅者图片
		$subscribers = wp_mfs_get_subscribers();
		MY_FEED_STATS::generate_image($subscribers);

	}
	// 显示订阅者数目
	wp_mfs_show_subscribers_detail();
}

/**
 * 删除旧的统计数据
 */
function wp_mfs_delete_old_useragent() {
	global $wpdb, $table_prefix;

	$sql = "DELETE FROM ".$table_prefix."mfs_user_agent WHERE is_fresh='N'";
	$wpdb->query($sql);
}

/**
 * 获取当天的订阅者数
 */
function wp_mfs_get_subscribers() {
	global $wpdb, $table_prefix;

	$subscribers = 0;
	$sql = "SELECT SUM(count) AS sum FROM ".$table_prefix."mfs_subscribers 
		WHERE stat_date = CURDATE()";
	$r = $wpdb->query($sql);

	if ($r > 0) {

		$row = $wpdb->last_result;

		$subscribers = $row[0]->sum;
	}

	return $subscribers;

}

/**
 *显示订阅者数目
 */
function wp_mfs_show_subscribers_detail() {
	global $wpdb, $table_prefix;

	$max_view_days = 30;		// 显示多少天之前的订阅者数
	$graph_width = 540;			// 条形图的宽度
	$bar_height = 200;			// 条形高度
	$bar_width = 14;			// 条形宽度

	$req_uri = $_SERVER['REQUEST_URI'];
	$req_uri = wp_mfs_delete_query_string($req_uri);


	// 取得要显示详细信息的日期
	$display_date = $_GET['mfs_d'];

	// 检查日期格式，如果不是标准的日期格式则不予接受
	if (!preg_match("/\d{4}-\d{2}-\d{2}/", $display_date)) $display_date = "";
?>
<style>
a.mfs_bar {
	float: left;
	border-style: solid;
	border-width: 1px;
	border-color: #DDD #888 #888 #DDD;
	background-color: #BDB;
	text-align:center;
	font-weight: bold;
	font-size: small;
	width: <?php echo $bar_width; ?>px;
	color: #FFF;
	display: block;
}
a.mfs_active {
	background-color: #88C98E;
}

a.mfs_bar:link { color: #FFF; }
a.mfs_bar:active { color: #FFF; }
a.mfs_bar:visited { color: #FFF; }
a.mfs_bar:hover { background-color: #88C98E; color: #88B; }

table#subscribers {
	border-top: solid 1px #888;
	border-left: solid 1px #888;
}

table#subscribers td, table#subscribers th {
	border-right: solid 1px #888;
	border-bottom: solid 1px #888;
}

</style>
<div class="wrap">
<h2>Feed订阅统计</h2>
<?php

	// 统计每天的订阅者数
	$sql = "SELECT SUM(count) AS sum, DATEDIFF(CURDATE(),stat_date) AS day FROM ".$table_prefix."mfs_subscribers 
		WHERE stat_date >= DATE_SUB(CURDATE(), INTERVAL $max_view_days DAY)
		GROUP BY stat_date ORDER BY stat_date DESC";
	$r = $wpdb->query($sql);

	if ($r > 0) {

		$row = $wpdb->last_result;

		$subscribers = array();
		$max = 0;

		for ($i=0; $i<$r; $i++) {
			$day = $row[$i]->day;
			$num = $row[$i]->sum;
			$subscribers[$day] = $num;
			if ($num > $max) $max = $num;
		}

		// 绘制条形图
?>
<div style="width:<?php echo $graph_width;?>px">
	<div style="width:100%;text-align:right"><?php echo $max;?></div>
	<div style="width:100%;border-top:solid 1px #BBB">
<?php
		// 依次显示每一天的条形图
		$now = time();

		// 如果日期参数未指定，则选择今天作为显示日期
		if (empty($display_date) || !$display_date) $display_date = date('Y-m-d', $now);

		// 要求日期的订阅者数
		$today_subscribers = 0;

		// 依次显示每一个柱状图
		for ($i = $max_view_days-1; $i >= 0; $i--) {

			// 取得订阅者数
			if (isset($subscribers[$i])) $s = $subscribers[$i];
			else $s = 0;

			// 取得当天日期
			$timestamp = $now - $i * 86400;
			$date = date('Y-m-d', $timestamp);
			$weekday = substr('MTWTFSS',date('w',$timestamp),1);

			// 计算条形图的高度
			$height = (int)($bar_height * $s / $max);
			if ($height < 3) $height = 3;
			$margin = $bar_height - $height + 1;
			$style = "margin-top:${margin}px; height:${height}px;";
			if ($height <= 16) $style .= "font-size: 1px;";

			// 如果显示的是要求日期的条形图，则改变其颜色，并记录下订阅者数目以供下面显示使用
			$display_css_class = "";
			if ($display_date == $date) {
				$display_css_class = "mfs_active";
				$today_subscribers = $s;
			}

#			echo "<a href='$req_uri&mfs_d=$date' title='$date, $s 个订阅者'>\n";
#			echo "<div class='mfs_bar $display_css_class' style='margin-top:${margin}px; height:${height}px;'>\n";
#			if ($height > 16) echo $weekday; 
#			echo "</div></a>\n";
			echo "<a class='mfs_bar $display_css_class' style='$style' href='$req_uri&mfs_d=$date' title='$date, $s 个订阅者'>";
			if ($height > 16) echo $weekday; 
			echo "</a>\n";
		}
?>
	</div>
	<div style="clear:both;margin-bottom:10px;"></div>
</div>
<?php
		// 显示要求日期的订阅者
		echo "<h3>$display_date 的订阅者：$today_subscribers</h3>";

		// 显示当前的订阅者详细情况
		$sql = "SELECT r.name, r.type, r.description, s.count 
			FROM ".$table_prefix."mfs_readers r, ".$table_prefix."mfs_subscribers s
			WHERE r.ID=s.reader_id AND s.stat_date='$display_date'
			ORDER BY type";
		$r = $wpdb->query($sql);

		if ($r > 0) {

			// 显示订阅者详细数目
			echo "<table width='$graph_width' id='subscribers' cellspacing='0' cellpadding='2'><tr><th>名称</th><th>类型</th><th>订阅数</th></tr>";
			$row = $wpdb->last_result;
			$type_name = array("online"=>"在线","offline"=>"离线");

			for ($i = 0; $i < $r; $i++) {

				echo "<tr>\n";
				echo "<td>".$row[$i]->name."</td>\n";
				echo "<td>".$type_name[$row[$i]->type]."</td>\n";
				echo "<td align='right'>".$row[$i]->count."</td>\n";
				echo "</tr>\n";
			}
			echo "</table>\n";
		}


		// 显示编辑阅读器属性的链接
		echo "<h3>编辑阅读器属性</h3>\n";
		echo "<p><a href='$req_uri&f=e&t=all'>编辑所有阅读器属性</a>, <a href='$req_uri&f=e&t=undef'>编辑所有未定义阅读器属性</a></p>";

	} else {
		echo "<p>Oops...或许你统计的时间太短，统计结果还没出来……再耐心地等待一天吧。</p>";
	}

	// 显示选项
?>
<h3>选项</h3>
<form action="<?php echo $req_uri;?>&f=uo" method="post">
订阅者图片的生成路径 <input type='text' name='img_path' value='<?php echo get_option('wp_mfs_imgpath'); ?>'/><br/>
订阅者图片的颜色 <input type='text' name='img_color' value='<?php echo get_option('wp_mfs_imgcolor'); ?>'/><br/>
订阅者图片上显示的网站名称 <input type='text' name='sitename' value='<?php echo get_option('wp_mfs_sitename'); ?>'/><br/>
生成的订阅者图片如下：<img src="<?php echo get_settings('home'); ?>/feeds.png"><br/>
<input type='submit' value='保存'/>
</form>


<h3>重新生成订阅者图片</h3>
<form action="<?php echo $req_uri;?>&f=rg" method="post">
<input type='submit' value='重新生成订阅者图片'/>(不会重新统计订阅者数)
</form>

<h3>清除过去的UserAgent数据</h3>
可以将以前的UserAgent数据全部清除，减小数据库空间占用。
<form action="<?php echo $req_uri;?>&f=du" method="post">
<input type='submit' value='清除以前的UserAgent数据'/>
</form>

</div>
<?php
}

/**
 * 编辑阅读器属性
 */
function wp_mfs_edit_readers_definition() {
	global $wpdb, $table_prefix;

	// 取得编辑属性的范围, all=编辑所有阅读器，undef=编辑未定义阅读器
	$t = $_GET['t'];

	// 取得页面URL
	$req_uri = $_SERVER['REQUEST_URI'];
	$req_uri = wp_mfs_delete_query_string($req_uri);

?>
<style>
table#reader_editor {
	margin: 10px;
}

table#reader_editor th {
	text-align: left;
}
table#reader_editor td {
	vertical-align: top;
}
</style>
<div class="wrap">
<h2>编辑阅读器属性</h2>
<?php

	// 取得要编辑的阅读器的定义
	$sql = "SELECT * from ".$table_prefix."mfs_readers";
	if ($t != 'all') $sql .= " WHERE description=''";
	$sql .= " ORDER BY ID";

	$r = $wpdb->query($sql);
	if ($r > 0) {
		$row = $wpdb->last_result;

		// 显示编辑阅读器用的表单
		echo "<form action='$req_uri&f=es' method='post'>\n";
		echo "<table id='reader_editor' width='100%'>\n";
		echo "<tr><th>ID</th><th>阅读器名</th><th>识别字符串</th><th>类别</th><th>描述</th></tr>\n";

		for ($i = 0; $i < $r; $i++) {
			echo "<tr>";
			echo "<input type='hidden' name='id[]' value='".$row[$i]->ID."'/>\n";
			echo "<td><strong>".$row[$i]->ID."</strong></td>\n";
			echo "<td><input type='text' size='30' name='name[]' value='".$row[$i]->name."'/></td>\n";
			echo "<td><input type='text' size='30' name='identifier[]' value='".$row[$i]->identifier."'/></td>\n";
			echo "<td><input type='text' size='10' name='type[]' value='".$row[$i]->type."'/></td>\n";
			echo "<td><textarea cols='40' rows='2' name='description[]'>".$row[$i]->description."</textarea></td>\n";
			echo "</tr>\n";
		}

		echo "</table>\n";
		echo "<input type='submit' value='保存'/> 或者<a href='$req_uri'>取消</a>";
		echo "</form>\n";
	}

?>
</div>
<?php
}


/**
 * 保存阅读器属性
 */
function wp_mfs_save_readers_definition() {
	global $wpdb, $table_prefix;

	$ids = $_POST["id"];
	$identifiers = $_POST["identifier"];
	$names = $_POST["name"];
	$types = $_POST["type"];
	$descriptions = $_POST["description"];


	// 依次更新每一条记录
	foreach ($ids as $key => $id) {

		$identifier = $identifiers[$key];
		$name = $names[$key];
		$type = $types[$key];
		$description = $descriptions[$key];

		$sql = "UPDATE ".$table_prefix."mfs_readers SET 
			identifier='$identifier',
			name='$name',
			type='$type',
			description='$description'
			WHERE ID=$id";
		$wpdb->query($sql);
	}
}


/**
 * 删除所有的query string
 */
function wp_mfs_delete_query_string($uri) {

	$uri = preg_replace("/&+mfs_d=\d+-\d+-\d+/","",$uri);
	$uri = preg_replace("/&+f=e&t=(all|undef)/","",$uri);
	$uri = preg_replace("/&+f=es/","",$uri);

	return $uri;
}

/**
 * 保存选项
 */
function wp_mfs_save_option() {
	global $wpdb;
	$img_path = $_POST["img_path"];
	$img_color = $_POST["img_color"];
	$sitename = $_POST["sitename"];

	update_option('wp_mfs_imgpath', $img_path);
	update_option('wp_mfs_imgcolor', $img_color);
	update_option('wp_mfs_sitename', $sitename);

	// 生成测试用图片
	MY_FEED_IMAGE::generate_image(12345, $img_color, $sitename, WP_MFS_ABSPATH . 'feeds-sample.png');
}


add_action("init", array('MY_FEED_STATS', 'feed_request'));
add_action("admin_menu", array('MY_FEED_STATS', 'add_admin_menu'));

